const jwt  = require('jsonwebtoken');
const bcrypt = require('bcryptjs');

const { blog_user, blog_roles, blog_menus, role_menus, user_roles } = require('@/model'); // 引入用户模型
const { Op } = require('sequelize'); // 引入操作符
const env = require('@/config/config.default');
const { buildMenuTree } = require('@/utils/format');
class UserService {
  /**
   * 创建用户
   * @param {Object} params - 用户信息对象
   * @param {Array} [roleIds] - 角色ID数组
   * @returns {Promise<Object>} 返回创建的用户信息（不含密码字段）
   * @description 如果未提供头像，会随机分配一个默认头像
   */
  async createUser({ roleIds, ...params }) { // 创建用户
    if (!params.avatar) {
      const domain = env.BASE_URL;
      const avatarList = [
        '/local/avatar/1.png',
        '/local/avatar/2.png',
        '/local/avatar/3.png',
        '/local/avatar/4.png',
        '/local/avatar/5.png',
        '/local/avatar/6.png'
      ]
      params.avatar = domain+avatarList[Math.floor(Math.random() * avatarList.length)]; // 随机生成头像
    } 
    params.password = params.password || '123456';
    const res = await blog_user.create(params); // 调用模型创建用户
    if (!res || !res.dataValues) {
      return {
        code: 400,
        message: '注册失败',
      };
    } else {
      if(roleIds && roleIds.length) await res.setRoles(roleIds); // 设置用户角色关系
      delete res.dataValues.password; // 移除 password 字段
    }
    return res.dataValues; // 返回用户信息
  }

  async login(params) {
    const res = await blog_user.findOne({ // 查询用户
      where: {
        username: params.username,
      }
    });
    const user = res?.dataValues; // 获取用户信息
    if (!user) {
      return {
        code: 401,
        message: '用户名不存在',
      };
    }
    const valid = bcrypt.compareSync(params.password, res.password); // 验证密码
    if (!valid) {
      return {
        code: 401,
        message: '密码错误',
      };
    }
    // 更新last_login_ip 和 last_login_time
    if (params.ip) await blog_user.update({ last_login_ip: params.ip, last_login_time: new Date() }, { where: { id: user.id } });
    const token = jwt.sign(
      user,  // 传入用户信息
      process.env.JWT_SECRET, // 密钥
      { expiresIn: '1d' }  // 设置过期时间 1天
    ); // 生成 token
    delete user.password; // 删除密码
    return {
      token,
      userInfo: user,
    }
  }

  async getUserList(params = {}) { // 获取用户列表
    console.log('params', params, );
    const queryOptions = {
      order: [['createdAt', 'DESC']],
      attributes: { exclude: ['password'] }, // 排除密码字段
      include: [
        {
          model: blog_roles, // 关联角色模型
          as: 'roles', // 使用模型中定义的别名
          through: { attributes: [] }, // 不返回中间表数据
        }
      ]
    };

    // 如果传入分页参数，添加分页选项
    if (params.current && params.pageSize) {
      queryOptions.offset = (params.current - 1) * params.pageSize;
      queryOptions.limit = params.pageSize;

      const res = await blog_user.findAndCountAll(queryOptions);
      return res ? {
        list: res.rows,
        total: res.count,
        current: params.current,
        pageSize: params.pageSize
      } : null;
    } else {
      // 不传分页参数，查询所有数据
      const res = await blog_user.findAll(queryOptions);
      return res ? {
        list: res,
        total: res.length
      } : null;
    }
  }
  async getUserInfo({ username, id, nickname, qq, email }) { // 获取用户信息
    const whereClause = { username, id, nickname, qq, email };
    Object.keys(whereClause).forEach(key => { // 删除为 undefined 的属性
      if (whereClause[key] === undefined) delete whereClause[key];
    });

    const res = await blog_user.findOne({ // 查询用户信息
      where: whereClause,
      attributes: {
        exclude: ['password'], // 排除密码
      },
      include: [
        {
          model: blog_roles, // 角色模型
          as: 'roles', // 使用别名
          include: [
            {
              model: blog_menus, // 用户模型
              as: 'menus', // 使用别名
              through: { attributes: [] }, // 不返回中间表字段
            },
          ],
        },
      ]
    });
    if(res?.avatar&&!res.avatar.startsWith('http')) {
      res.avatar = process.env.BASE_URL + res.avatar;
    }

    return res;
  }

  /**
   * 获取用户菜单和按钮权限
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} 返回包含菜单树和按钮权限的对象
   */
  async getUserMenuAndButtons(userId) {
    const userRoles = await user_roles.findAll({
      where: { user_id: userId }
    });
    if(!userRoles || !userRoles.length) return { menus: [], buttons: [] };
    const roleIds = userRoles.map(userRole => userRole.role_id);
    const roleMenus = await role_menus.findAll({
      where: { role_id: roleIds },
      include: [
        { model: blog_menus, as: 'menu' }
      ]
    });
    const allMenus = roleMenus.map(roleMenu => roleMenu.menu);
    const menus = allMenus.filter(menu => menu.type === 1); // 过滤出菜单
    const buttons = allMenus.filter(menu => menu.type === 2); // 过滤出按钮
    return {
      menus: buildMenuTree(menus),
      buttons
    };
  }

  /**
   * 根据用户ID删除用户
   * @param {number} id - 要删除的用户ID
   * @returns {Promise<number>} 返回删除结果，1表示成功，0表示失败
   */
  async deleteById(id) { // 删除用户
    const res = await blog_user.destroy({
      where: {
        id,
      }
    });
    console.log('删除用户', res);
    return res; // 返回结果 1表示删除成功，0表示删除失败
  }

  async deleteByIds(ids) { // 批量删除用户
    const res = await blog_user.destroy({
      where: {
        id: {
          [Op.in]: ids, // 使用 $in 操作符处理数组 SELECT * FROM table WHERE id IN (1, 2, 3, ...)
        },
      }
    });
    console.log('批量删除用户', res);
    return res; // 返回结果 1表示删除成功，0表示删除失败
  }

  updateUser = async ({id, roleIds,...params})=>{ // 更新用户
    Object.keys(params).forEach((key) => {
      if (params[key] === undefined) {
        delete params[key];
      }
    });
    if(id) { // 更新用户
      const [ updateRows ] = await blog_user.update(params, { where: { id } });
      if (roleIds && updateRows) {
        const user = await blog_user.findByPk(id);
        await user.setRoles(roleIds);
      }
      return updateRows 
    } else {  // 新增用户
      return this.createUser({ ...params, roleIds })
    }
  }

  async updatePassword(id, oldPassword, newPassword) { // 修改密码
    const user = await blog_user.findByPk(id);
    if (!user) {
      throw new Error('用户不存在');
    }
    const valid = bcrypt.compareSync(oldPassword, user.password); // 验证密码
    if (!valid) {
      throw new Error('旧密码错误');
    }
    user.password = bcrypt.hashSync(newPassword, 10); // 加密新密码
    await user.save(); // 保存用户
    return true;
  }

}

module.exports = new UserService();